'''
Author: didiplus
Date: 2024-11-26 16:12:47
LastEditTime: 2024-12-25 14:27:12
LastEditors: didiplus
Description: 
FilePath: \pythonscript\AutoNetCheck\main.py
'''
import contextlib
from netmiko import ConnectHandler
from openpyxl import load_workbook
from loguru import logger
import textfsm
import toml
import json,io


# 加载配置文件
config = toml.load("config.toml")
logger.add("inspection.log")

def read_excel_data(file_path,sheet_name,keys):
    """
    通用函数：读取 Excel 数据
    :param file_path: 文件路径
    :param sheet_name: 表格名称
    :param keys: 字段名列表，用于将每行数据映射成字典
    :return: 处理后的数据列表
    """
    workbook = load_workbook(file_path)
    sheet = workbook[sheet_name]
    data = []
    for row in sheet.iter_rows(min_row=2, values_only=True):
        # 将每行数据与 keys 对应，并忽略超出 keys 的列
        row_dict = {keys[i]: row[i] if i < len(row) else None for i in range(len(keys))}
        data.append(row_dict)
    return data

def read_device_info(file_path):
    """读取设备信息"""
    keys = ["ip", "device_type", "username", "password", "port"]
    devices = read_excel_data(file_path, "devices", keys)
    # 如果端口为空，默认赋值为 22
    for device in devices:
        device["port"] = device["port"] or 22
    return devices




def read_inspection_commands(file_path,sheet_name):
    """读取巡检命令"""
    keys = ["command", "desc", "template"]
    return read_excel_data(file_path, sheet_name, keys)


def execute_command(device, command):
    """连接设备并执行命令"""
    logger.info(f"连接设备 {device['ip']}，执行命令：{command}")
    try:
        connection = ConnectHandler(**device)
        output = connection.send_command(command)
        connection.disconnect()
        return output
    except Exception as e:
        logger.error(f"设备 {device['ip']} 命令执行失败：{e}")
        return None

def parse_output(output, template_file):
    """使用 TextFSM 解析命令输出"""
    template=textfsm.TextFSM(io.StringIO(template_file))
    results= template.ParseText(output)
    # 获取解析结果和变量名
    parsed_data = [dict(zip(template.header, result)) for result in results]
    return parsed_data


def start_inspection():
    """巡检主逻辑"""
    devices = read_device_info("devices.xlsx")
    commonds = read_inspection_commands("devices.xlsx","commands")
    for device in devices:
        for commond  in  commonds:
            output = execute_command(device, commond.get("command"))
            print(output)
            if output:
                # 加载 TTP 模板
                template = f"{config['config']['template_path']}/{device.get('device_type')}/{commond.get('template')}"
                with open(template, "r") as file:
                    templates = file.read()

                # 解析结果
                result = parse_output(output, templates)
                print(result)
                logger.info(f"设备 {device['ip']} {commond.get('title')} 结果：")
                logger.info(json.dumps(result, indent=4, ensure_ascii=False))

if __name__ == "__main__":
    start_inspection()
    






